Global Forest Area Fluctiations from 1993 to 2021

Introduction

The dataset used in this report was collected on the 25th of January 2024 from The Data Worldbank. The data falls under the License CC-BY 4.0, which allows public use.

Being interested in the environmental state of the world, I wanted to know what is happening to our forests. As we likely all know, global warming is threatening our world, and to make an impact on reversing and preserving our planet, I think it’s important that people can visualize the impact of our actions, rather than hear about this. That is the goal of this project.

To do this I’ve asked the following questions:

  1. Which 5 countries have suffered the highest loss in forest area?
  2. Which countries have gained the most forest area over time?
  3. Per year, is there a loss, neutrality, or increase in forest area globally?

Create an in-memory database and import libraries.

Locate dataset and import libraries.

Code
database_loc = R"C:\Users\ERMCl\Documents\FreelanceWork\Portfolio\Forest_Area_Internationally_2024.0125\API_6_DS2_en_csv_v2_6303688.csv"


import duckdb
connection = duckdb.connect(database=':memory:')
import pandas as pd
import geopandas as gpd

import plotly.graph_objects as go
import plotly.express as px

Copy paste code output to help create the database.

Code
# x = 1993
# while x < 2023:
#     print(f"CONCAT(y{x}, '%') AS y{x},"),
#     x += 1
# print("done")


# while x < 2023:
#     print(f"y{x} INT64,"),
#     x += 1
# print("done")


# while x < 2023:
#     print(f"y{x} = CONCAT(y{x}, '%'),"),
#     x += 1
# print("done")

Create in-memory database from the dataset to allow faster data proccessing.

Code
create_table_query = """
CREATE TABLE IF NOT EXISTS ForestDB (
    Country_Name string,
    Country_Code string,
    Indicator_Name string,
    Indicator_Code string,
    y1960 INT64,
    y1961 INT64,
    y1962 INT64,
    y1963 INT64,
    y1964 INT64,
    y1965 INT64,
    y1966 INT64,
    y1967 INT64,
    y1968 INT64,
    y1969 INT64,
    y1970 INT64,
    y1971 INT64,
    y1972 INT64,
    y1973 INT64,
    y1974 INT64,
    y1975 INT64,
    y1976 INT64,
    y1977 INT64,
    y1978 INT64,
    y1979 INT64,
    y1980 INT64,
    y1981 INT64,
    y1982 INT64,
    y1983 INT64,
    y1984 INT64,
    y1985 INT64,
    y1986 INT64,
    y1987 INT64,
    y1988 INT64,
    y1989 INT64,
    y1990 INT64,
    y1991 INT64,
    y1992 INT64,
    y1993 INT64,
    y1994 INT64,
    y1995 INT64,
    y1996 INT64,
    y1997 INT64,
    y1998 INT64,
    y1999 INT64,
    y2000 INT64,
    y2001 INT64,
    y2002 INT64,
    y2003 INT64,
    y2004 INT64,
    y2005 INT64,
    y2006 INT64,
    y2007 INT64,
    y2008 INT64,
    y2009 INT64,
    y2010 INT64,
    y2011 INT64,
    y2012 INT64,
    y2013 INT64,
    y2014 INT64,
    y2015 INT64,
    y2016 INT64,
    y2017 INT64,
    y2018 INT64,
    y2019 INT64,
    y2020 INT64,
    y2021 INT64,
    y2022 INT64
);
"""
connection.execute(create_table_query)

load_data_query = FR"""
INSERT INTO ForestDB
SELECT
    Country_Name,
    Country_Code,
    Indicator_Name,
    Indicator_Code,
    y1960,
    y1961,
    y1962,
    y1963,
    y1964,
    y1965,
    y1966,
    y1967,
    y1968,
    y1969,
    y1970,
    y1971,
    y1972,
    y1973,
    y1974,
    y1975,
    y1976,
    y1977,
    y1978,
    y1979,
    y1980,
    y1981,
    y1982,
    y1983,
    y1984,
    y1985,
    y1986,
    y1987,
    y1988,
    y1989,
    y1990,
    y1991,
    y1992,
    y1993,
    y1994,
    y1995,
    y1996,
    y1997,
    y1998,
    y1999,
    y2000,
    y2001,
    y2002,
    y2003,
    y2004,
    y2005,
    y2006,
    y2007,
    y2008,
    y2009,
    y2010,
    y2011,
    y2012,
    y2013,
    y2014,
    y2015,
    y2016,
    y2017,
    y2018,
    y2019,
    y2020,
    y2021,
    y2022
FROM
    read_csv_auto('{database_loc}');
"""

connection.execute(load_data_query)


database = connection.execute("SELECT* FROM ForestDB").df()

Query 1. Which 5 countries have suffered the highest loss in forest area?

Run a query to calculate the change in forest area and order the results in ascending order. Limit output to first 5 rows.

Code
query = """
SELECT 
    DISTINCT Country_Name AS 'Country Name',
    Indicator_Name AS 'Indicator Name',
    y1993,
    y1994,
    y1995,
    y1996,
    y1997,
    y1998,
    y1999,
    y2000,
    y2001,
    y2002,
    y2003,
    y2004,
    y2005,
    y2006,
    y2007,
    y2008,
    y2009,
    y2010,
    y2011,
    y2012,
    y2013,
    y2014,
    y2015,
    y2016,
    y2017,
    y2018,
    y2019,
    y2020,
    y2021,
    (y2021 - y1993) AS '% Change in Forest Area (1993-2021)'
FROM ForestDB
WHERE Indicator_Name ='Forest area (% of land area)'
ORDER BY (y2021 - y1993) ASC
LIMIT 5;
"""
table = connection.execute(query).df()

Reorganize the table.

Code
table_melted = table.melt(id_vars=['Country Name', 'Indicator Name', '% Change in Forest Area (1993-2021)'], var_name='Year', value_name='% Forest Area')
table_melted['Year'] = table_melted['Year'].str.extract('(\d+)', expand=False).astype(int)

table_melted.tail(5)
Country Name Indicator Name % Change in Forest Area (1993-2021) Year % Forest Area
140 Nicaragua Forest area (% of land area) -24 2021 27
141 Paraguay Forest area (% of land area) -22 2021 40
142 Northern Mariana Islands Forest area (% of land area) -19 2021 53
143 Cambodia Forest area (% of land area) -17 2021 45
144 Gambia, The Forest area (% of land area) -16 2021 23

Visualization of the table.

Code
# Create the plot
fig = px.line(table_melted, 
              x='Year', 
              y='% Forest Area', 
              color='Country Name',
              line_shape='linear',
              hover_name="Country Name",
              custom_data=['% Change in Forest Area (1993-2021)']
                )


# Gray out all lines
fig.update_traces(line=dict(color='lightgray'))


# Define Country with the highest total Change of Forest Area from 1993 to 2021
highest_loss_country = table_melted.loc[table_melted['% Change in Forest Area (1993-2021)'].idxmin()]['Country Name']


# Add annotations to the country with the highest Forest loss
name_data = table_melted[table_melted['Country Name'] == highest_loss_country].iloc[10]
fig.add_annotation(x=name_data['Year'], y=name_data['% Forest Area'],
                   text=f"<b>{highest_loss_country}<b>",
                   showarrow=False, yshift=20, font=dict(color='white'))

loss_data_point = table_melted[(table_melted['Country Name'] == highest_loss_country) & (table_melted['Year'] == table_melted['Year'].max())]
fig.add_annotation(x=loss_data_point['Year'].values[0], y=loss_data_point['% Forest Area'].values[0],
                   text=f"<b>Total % Change: {loss_data_point['% Change in Forest Area (1993-2021)'].values[0]}%<b>",
                   showarrow=False, yshift=25, font=dict(color='white'))


# Edit hover ---> Research how to edit hover!!! current hover is not correct
hover_template = "<b>%{hovertext}</b><br>" \
                 "Year: %{x}<br>" \
                 "Forest Area: %{y}% <br>" \
                 "<i>Total Area Change: %{customdata}% <i><extra></extra>"
#                 "&nbsp;<br>" \ -> for added enter
fig.update_traces(hovertemplate=hover_template)



# Edit Layout of Graph
fig.update_traces(hoverlabel=dict(font=dict(color='black'), bgcolor='lightgray')) #hoverdata

fig.update_traces(selector={'name': highest_loss_country}, line=dict(color='red'))  #selector hover data
#fig.update_traces(hoverlabel=dict(font=dict(color='rgb(102,0,0)')), selector={'name': highest_loss_country})
fig.update_traces(hoverlabel=dict(font=dict(color='white'), bgcolor='rgb(128,0,0)'), selector={'name': highest_loss_country})


fig.update_xaxes(showgrid=False, range=[1993, 2021])
fig.update_yaxes(showgrid=False, range=[0, 100])
fig.update_layout(showlegend=False, title_x=0.5, title=dict(text='<b>The Country With The Highest Loss of Forest Area From 1993 to 2021<b>', font=dict(size=18)),
                  paper_bgcolor='rgb(17,17,17)', plot_bgcolor='rgb(17,17,17)', font=dict(color='white'))

fig.update_layout(width=790, height=500, margin=dict(l=100, r=100, b=100, t=100))

#Call for graph
fig.show()

Visualization with added animated time-line.

Code
# Static Graph
fig = px.line(table_melted, 
              x='Year', 
              y='% Forest Area', 
              color='Country Name',
              line_shape='linear',
              hover_name="Country Name",
              custom_data=['% Change in Forest Area (1993-2021)']
              )
fig.update_traces(line=dict(color='lightgray'))

highest_loss_country = table_melted.loc[table_melted['% Change in Forest Area (1993-2021)'].idxmin()]['Country Name']

name_data = table_melted[table_melted['Country Name'] == highest_loss_country].iloc[10]
fig.add_annotation(x=name_data['Year'], y=name_data['% Forest Area'],
                   text=f"<b>{highest_loss_country}<b>",
                   showarrow=False, yshift=20, font=dict(color='white'))

loss_data_point = table_melted[(table_melted['Country Name'] == highest_loss_country) & (table_melted['Year'] == table_melted['Year'].max())]
fig.add_annotation(x=loss_data_point['Year'].values[0], y=loss_data_point['% Forest Area'].values[0],
                   text=f"<b>Total % Change: {loss_data_point['% Change in Forest Area (1993-2021)'].values[0]}%<b>",
                   showarrow=False, yshift=25, font=dict(color='white'))

hover_template = "<b>%{hovertext}</b><br>" \
                 "Year: %{x}<br>" \
                 "Forest Area: %{y}% <br>" \
                 "<i>Total Area Change: %{customdata}% <i><extra></extra>"
fig.update_traces(hovertemplate=hover_template)

fig.update_traces(hoverlabel=dict(font=dict(color='black'), bgcolor='lightgray'))
fig.update_traces(selector={'name': highest_loss_country}, line=dict(color='red'))
fig.update_traces(hoverlabel=dict(font=dict(color='white'), bgcolor='rgb(128,0,0)'), selector={'name': highest_loss_country})
fig.update_xaxes(showgrid=False, range=[1993, 2021])
fig.update_yaxes(showgrid=False, range=[0, 100])
fig.update_layout(showlegend=False, title_x=0.5, title=dict(text='<b>The Country With The Highest Loss of Forest Area From 1993 to 2021<b>', font=dict(size=18)),
                  paper_bgcolor='rgb(17,17,17)', plot_bgcolor='rgb(17,17,17)', font=dict(color='white'))
fig.update_layout(width=790, height=500, margin=dict(l=100, r=100, b=100, t=100))



# Add frames for animation
frames = []

for year in sorted(table_melted['Year'].unique()):
    frame_data = table_melted[table_melted['Year'] <= year]
    frame_traces = [
        go.Scatter(
            x=frame_data[frame_data['Country Name'] == country]['Year'], 
            y=frame_data[frame_data['Country Name'] == country]['% Forest Area'],
            mode='lines',
            line=dict(color='red' if country == highest_loss_country else 'gray'),
            name=country
        ) for country in frame_data['Country Name'].unique()
    ]

    frame_traces.append(go.Scatter(
        x=[max(frame_data['Year'])],
        y=[max(frame_data['% Forest Area'])],
        text=[str(year)],
        mode="text",
        showlegend=False
    ))

    frame = go.Frame(data=frame_traces, name=str(year))
    frames.append(frame)

fig.frames = frames

# Add animation controls
fig.update_layout(
    updatemenus=[{
        'type': 'buttons',
        'buttons': [{
            'label': 'Play',
            'method': 'animate',
            'args': [None, {'frame': {'duration': 300, 'redraw': True}, 
                            'fromcurrent': True, 
                            'transition': {'duration': 300, 'easing': 'linear'}}]
        }],
        'direction': 'left',
        'showactive': False,
        'x': -0.05,
        'xanchor': 'right',
        'y': 0,
        'yanchor': 'top'
    }],
    sliders=[{
        'steps': [{'method': 'animate', 
                   'args': [[f'{year}'], 
                            {'frame': {'duration': 400, 'redraw': True}, 
                             'mode': 'immediate',
                             'transition': {'duration': 200}}],
                   'label': str(year)} for year in sorted(table_melted['Year'].unique())]
    }]
)

# Show the plot
fig.show()

Query 2. Which countries have gained the most forest area over time?

Run query for full table.

Code
#Create database with only Indicator_Name ='Forest area (% of land area)'

query2 = """
SELECT 
    DISTINCT Country_Name AS 'Country Name',
    Indicator_Name AS 'Indicator Name',
    y1993,
    y1994,
    y1995,
    y1996,
    y1997,
    y1998,
    y1999,
    y2000,
    y2001,
    y2002,
    y2003,
    y2004,
    y2005,
    y2006,
    y2007,
    y2008,
    y2009,
    y2010,
    y2011,
    y2012,
    y2013,
    y2014,
    y2015,
    y2016,
    y2017,
    y2018,
    y2019,
    y2020,
    y2021,
    (y2021 - y1993) AS '% Change in Forest Area (1993-2021)'
FROM ForestDB
WHERE Indicator_Name ='Forest area (% of land area)'
ORDER BY (y2021 - y1993) DESC
LIMIT 5;
"""
Table2 = connection.execute(query2).df()

Reorganize the table.

Code
table_melted2 = Table2.melt(id_vars=['Country Name', 'Indicator Name', '% Change in Forest Area (1993-2021)'], var_name='Year', value_name='% Forest Area')
table_melted2['Year'] = table_melted2['Year'].str.extract('(\d+)', expand=False).astype(int)
table_melted2
Country Name Indicator Name % Change in Forest Area (1993-2021) Year % Forest Area
0 Bhutan Forest area (% of land area) 18 1993 54
1 Viet Nam Forest area (% of land area) 16 1993 31
2 Puerto Rico Forest area (% of land area) 16 1993 40
3 Cuba Forest area (% of land area) 11 1993 20
4 Dominican Republic Forest area (% of land area) 10 1993 35
... ... ... ... ... ...
140 Bhutan Forest area (% of land area) 18 2021 72
141 Viet Nam Forest area (% of land area) 16 2021 47
142 Puerto Rico Forest area (% of land area) 16 2021 56
143 Cuba Forest area (% of land area) 11 2021 31
144 Dominican Republic Forest area (% of land area) 10 2021 45

145 rows × 5 columns

Visualization

Code
# Create the plot
fig2 = px.line(table_melted2, 
              x='Year', 
              y='% Forest Area', 
              color='Country Name',
              line_shape='linear',
              hover_name="Country Name",
              custom_data=['% Change in Forest Area (1993-2021)']
                )


# Gray out all lines
fig2.update_traces(line=dict(color='lightgray'))


# Define Country with the highest total gain of Forest Area from 1993 to 2021
highest_gain_country = table_melted2.loc[table_melted2['% Change in Forest Area (1993-2021)'].idxmax()]['Country Name']


# Add annotations to the country with the highest Forest gain
name_data = table_melted2[table_melted2['Country Name'] == highest_gain_country].iloc[10]
fig2.add_annotation(x=name_data['Year'], y=name_data['% Forest Area'],
                   text=f"<b>{highest_gain_country}<b>",
                   showarrow=False, yshift=20, font=dict(color='white'))

gain_data_point = table_melted2[(table_melted2['Country Name'] == highest_gain_country) & (table_melted2['Year'] == table_melted2['Year'].max())]
fig2.add_annotation(x=gain_data_point['Year'].values[0], y=gain_data_point['% Forest Area'].values[0],
                   text=f"<b>Total % Change: {gain_data_point['% Change in Forest Area (1993-2021)'].values[0]}%<b>",
                   showarrow=False, yshift=25, font=dict(color='white'))


# Edit hover ---> Research how to edit hover!!! current hover is not correct
hover_template = "<b>%{hovertext}</b><br>" \
                 "Year: %{x}<br>" \
                 "Forest Area: %{y}% <br>" \
                 "<i>Total Area Change: %{customdata}% <i><extra></extra>"
#                 "&nbsp;<br>" \ -> for added enter
fig2.update_traces(hovertemplate=hover_template)



# Edit Layout of Graph
fig2.update_traces(hoverlabel=dict(font=dict(color='black'), bgcolor='lightgray')) #hoverdata

fig2.update_traces(selector={'name': highest_gain_country}, line=dict(color='green'))  #selector hover data
#fig2.update_traces(hoverlabel=dict(font=dict(color='rgb(102,0,0)')), selector={'name': highest_gain_country})
fig2.update_traces(hoverlabel=dict(font=dict(color='white'), bgcolor='rgb(0,153,0)'), selector={'name': highest_gain_country})


fig2.update_xaxes(showgrid=False, range=[1993, 2021])
fig2.update_yaxes(showgrid=False, range=[0, 100])
fig2.update_layout(showlegend=False, title_x=0.5, title=dict(text='<b>The Country With The Highest Increase of Forest Area From 1993 to 2021<b>', font=dict(size=18)),
                  paper_bgcolor='rgb(17,17,17)', plot_bgcolor='rgb(17,17,17)', font=dict(color='white'))

fig2.update_layout(width=790, height=500, margin=dict(l=100, r=100, b=100, t=100))

#Call for graph
fig2.show()

The most Forest Area lost by a country from 1993 to 2021 is 24%, while the most gained by a country is 18%. Seeying these numbers, I’m interested to see how the total amount of global forest area has changed over the same amount of time.

Query 3. Per year, is there a loss, neutrality, or increase in forest area globally?

Confirm each row is unique

Code
# How many countries are there?
Q = """
SELECT
    Country_Name,
    y1993,
    y1994,
    y1995,
    y1996,
    y1997,
    y1998,
    y1999,
    y2000,
    y2001,
    y2002,
    y2003,
    y2004,
    y2005,
    y2006,
    y2007,
    y2008,
    y2009,
    y2010,
    y2011,
    y2012,
    y2013,
    y2014,
    y2015,
    y2016,
    y2017,
    y2018,
    y2019,
    y2020,
    y2021
    FROM ForestDB
    WHERE Indicator_Name ='Forest area (% of land area)' AND (y2021 - y1993) IS NOT NULL;
"""
TableX = connection.execute(Q).df()

Create copy paste for the next query

Code
x = 1993
#while x < 2023:
#    print(f"SUM(y{x}) AS 'Area {x}',")
#    x += 1
#print("done")
Code
query3 = """
SELECT 
    ROUND(SUM(y1993)/254,2) AS 'Area 1993',
    ROUND(SUM(y1994)/254,2) AS 'Area 1994',
    ROUND(SUM(y1995)/254,2) AS 'Area 1995',
    ROUND(SUM(y1996)/254,2) AS 'Area 1996',
    ROUND(SUM(y1997)/254,2) AS 'Area 1997',
    ROUND(SUM(y1998)/254,2) AS 'Area 1998',
    ROUND(SUM(y1999)/254,2) AS 'Area 1999',
    ROUND(SUM(y2000)/254,2) AS 'Area 2000',
    ROUND(SUM(y2001)/254,2) AS 'Area 2001',
    ROUND(SUM(y2002)/254,2) AS 'Area 2002',
    ROUND(SUM(y2003)/254,2) AS 'Area 2003',
    ROUND(SUM(y2004)/254,2) AS 'Area 2004',
    ROUND(SUM(y2005)/254,2) AS 'Area 2005',
    ROUND(SUM(y2006)/254,2) AS 'Area 2006',
    ROUND(SUM(y2007)/254,2) AS 'Area 2007',
    ROUND(SUM(y2008)/254,2) AS 'Area 2008',
    ROUND(SUM(y2009)/254,2) AS 'Area 2009',
    ROUND(SUM(y2010)/254,2) AS 'Area 2010',
    ROUND(SUM(y2011)/254,2) AS 'Area 2011',
    ROUND(SUM(y2012)/254,2) AS 'Area 2012',
    ROUND(SUM(y2013)/254,2) AS 'Area 2013',
    ROUND(SUM(y2014)/254,2) AS 'Area 2014',
    ROUND(SUM(y2015)/254,2) AS 'Area 2015',
    ROUND(SUM(y2016)/254,2) AS 'Area 2016',
    ROUND(SUM(y2017)/254,2) AS 'Area 2017',
    ROUND(SUM(y2018)/254,2) AS 'Area 2018',
    ROUND(SUM(y2019)/254,2) AS 'Area 2019',
    ROUND(SUM(y2020)/254,2) AS 'Area 2020',
    ROUND(SUM(y2021)/254,2) AS 'Area 2021'
    FROM ForestDB
    WHERE Indicator_Name ='Forest area (% of land area)' AND (y2021 - y1993) IS NOT NULL;
"""

#IS NOT NULL excludes 12 rows
#removed DISTINCT country_name as its confirmed country_name is already DISTINCT
Table3 = connection.execute(query3).df()

reconfigure the table to make it more readable

Code
table_melted3 = Table3.melt(var_name='Year', value_name='% Forest Area')
table_melted3['Year'] = table_melted3['Year'].str.extract('(\d+)', expand=False).astype(int)

table_melted3
Year % Forest Area
0 1993 33.00
1 1994 32.98
2 1995 32.93
3 1996 32.85
4 1997 32.82
5 1998 32.79
6 1999 32.77
7 2000 32.73
8 2001 32.67
9 2002 32.61
10 2003 32.60
11 2004 32.53
12 2005 32.48
13 2006 32.45
14 2007 32.40
15 2008 32.37
16 2009 32.32
17 2010 32.29
18 2011 32.26
19 2012 32.21
20 2013 32.15
21 2014 32.12
22 2015 32.09
23 2016 32.03
24 2017 31.97
25 2018 31.93
26 2019 31.86
27 2020 31.82
28 2021 31.77

Visualize the results #Create database with only Indicator_Name =‘Forest area (% of land area)’

Code
# Create the plot
fig3 = px.line(table_melted3, 
              x='Year', 
              y='% Forest Area', 
              line_shape='linear',
                )



# Edit hover ---> Research how to edit hover!!! current hover is not correct
hover_template = "Year: %{x}<br>" \
                 "Forest Area: %{y}% <br> <extra></extra>"
#                 "&nbsp;<br>" \ -> for added enter
fig3.update_traces(hovertemplate=hover_template)



# Edit Layout of Graph
fig3.update_traces(hoverlabel=dict(font=dict(color='white'), bgcolor='blue')) #hoverdata

fig3.update_xaxes(showgrid=False, range=[1993, 2021])
fig3.update_yaxes(showgrid=True, range=[20,40])
fig3.update_layout(showlegend=False, title_x=0.5, title=dict(text='<b>Global percentage of Forest Area from 1993 to 2021<b>', font=dict(size=18)),
                  paper_bgcolor='rgb(17,17,17)', plot_bgcolor='rgb(17,17,17)', font=dict(color='white'))

fig3.update_layout(width=790, height=500, margin=dict(l=100, r=100, b=100, t=100))

#Call for graph
fig3.show()

Display entire map

Run query for full table.

Code
#Create database with only Indicator_Name ='Forest area (% of land area)'

query3 = """
SELECT 
    DISTINCT Country_Name AS 'Country Name',
    Indicator_Name AS 'Indicator Name',
    y1993,
    y1994,
    y1995,
    y1996,
    y1997,
    y1998,
    y1999,
    y2000,
    y2001,
    y2002,
    y2003,
    y2004,
    y2005,
    y2006,
    y2007,
    y2008,
    y2009,
    y2010,
    y2011,
    y2012,
    y2013,
    y2014,
    y2015,
    y2016,
    y2017,
    y2018,
    y2019,
    y2020,
    y2021,
    (y2021 - y1993) AS '% Change in Forest Area (1993-2021)'
FROM ForestDB
WHERE Indicator_Name ='Forest area (% of land area)' AND (y2021 - y1993) IS NOT NULL
ORDER BY (y2021 - y1993) DESC;
"""
FullTable = connection.execute(query3).df()
FullTable
Country Name Indicator Name y1993 y1994 y1995 y1996 y1997 y1998 y1999 y2000 ... y2013 y2014 y2015 y2016 y2017 y2018 y2019 y2020 y2021 % Change in Forest Area (1993-2021)
0 Bhutan Forest area (% of land area) 54 64 64 64 65 65 65 65 ... 71 71 71 71 71 71 71 71 72 18
1 Viet Nam Forest area (% of land area) 31 32 33 33 34 35 35 38 ... 44 44 45 46 46 46 46 47 47 16
2 Puerto Rico Forest area (% of land area) 40 41 42 43 45 46 47 48 ... 56 56 56 56 56 56 56 56 56 16
3 Cuba Forest area (% of land area) 20 21 21 21 22 22 22 23 ... 30 30 31 31 31 31 31 31 31 11
4 Fiji Forest area (% of land area) 53 53 53 54 54 54 55 55 ... 60 60 61 61 61 62 62 62 63 10
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
249 Gambia, The Forest area (% of land area) 39 39 38 38 37 36 36 35 ... 28 27 27 26 26 25 25 24 23 -16
250 Cambodia Forest area (% of land area) 62 62 62 62 61 61 61 61 ... 54 52 50 49 48 47 47 46 45 -17
251 Northern Mariana Islands Forest area (% of land area) 72 72 71 71 71 70 70 69 ... 65 64 64 53 53 53 53 53 53 -19
252 Paraguay Forest area (% of land area) 62 62 61 60 60 59 59 58 ... 46 45 44 44 43 42 41 41 40 -22
253 Nicaragua Forest area (% of land area) 51 50 49 48 47 47 46 45 ... 33 33 32 32 31 30 29 28 27 -24

254 rows × 32 columns

Reorganize the table.

Code
table_melted_full = FullTable.melt(id_vars=['Country Name', 'Indicator Name', '% Change in Forest Area (1993-2021)'], var_name='Year', value_name='% Forest Area')
table_melted_full['Year'] = table_melted_full['Year'].str.extract('(\d+)', expand=False).astype(int)
table_melted_full
Country Name Indicator Name % Change in Forest Area (1993-2021) Year % Forest Area
0 Bhutan Forest area (% of land area) 18 1993 54
1 Viet Nam Forest area (% of land area) 16 1993 31
2 Puerto Rico Forest area (% of land area) 16 1993 40
3 Cuba Forest area (% of land area) 11 1993 20
4 Fiji Forest area (% of land area) 10 1993 53
... ... ... ... ... ...
7361 Gambia, The Forest area (% of land area) -16 2021 23
7362 Cambodia Forest area (% of land area) -17 2021 45
7363 Northern Mariana Islands Forest area (% of land area) -19 2021 53
7364 Paraguay Forest area (% of land area) -22 2021 40
7365 Nicaragua Forest area (% of land area) -24 2021 27

7366 rows × 5 columns

Visualization

Code
# Load world map GeoJSON file
world_map = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) #evertually change with the downloaded document
#world_map['geometry'] = world_map['geometry'].simplify(tolerance=0.01) #Adding this line makes running the code a bit faster


# Update the country names to match the one in world_map
table_melted_full.loc[table_melted_full['Country Name'] == 'United States', 'Country Name'] = 'United States of America'
table_melted_full.loc[table_melted_full['Country Name'] == 'Congo, Rep.', 'Country Name'] = 'Congo'
table_melted_full.loc[table_melted_full['Country Name'] == 'Congo, Dem. Rep.', 'Country Name'] = 'Dem. Rep. Congo'
table_melted_full.loc[table_melted_full['Country Name'] == 'Egypt, Arab Rep.', 'Country Name'] = 'Egypt'
table_melted_full.loc[table_melted_full['Country Name'] == 'Yemen, Rep.', 'Country Name'] = 'Yemen'
table_melted_full.loc[table_melted_full['Country Name'] == 'South Sudan', 'Country Name'] = 'S. Sudan'
table_melted_full.loc[table_melted_full['Country Name'] == 'Russian Federation', 'Country Name'] = 'Russia'
table_melted_full.loc[table_melted_full['Country Name'] == 'Venezuela, RB', 'Country Name'] = 'Venezuela'
table_melted_full.loc[table_melted_full['Country Name'] == 'Central African Republic', 'Country Name'] = 'Central African Rep.'
table_melted_full.loc[table_melted_full['Country Name'] == 'Dominican Republic', 'Country Name'] = 'Dominican Rep.'
table_melted_full.loc[table_melted_full['Country Name'] == 'Bahamas, The', 'Country Name'] = 'Bahamas'
table_melted_full.loc[table_melted_full['Country Name'] == "Cote d'Ivoire", 'Country Name'] = "Côte d'Ivoire"
table_melted_full.loc[table_melted_full['Country Name'] == 'Iran, Islamic Rep.', 'Country Name'] = 'Iran'
table_melted_full.loc[table_melted_full['Country Name'] == 'Syrian Arab Republic', 'Country Name'] = 'Syria'
table_melted_full.loc[table_melted_full['Country Name'] == 'Turkiye', 'Country Name'] = 'Turkey'
table_melted_full.loc[table_melted_full['Country Name'] == 'Viet Nam', 'Country Name'] = 'Vietnam'
table_melted_full.loc[table_melted_full['Country Name'] == 'Lao PDR', 'Country Name'] = 'Laos'
table_melted_full.loc[table_melted_full['Country Name'] == "Korea, Dem. People's Rep.", 'Country Name'] = 'North Korea'
table_melted_full.loc[table_melted_full['Country Name'] == 'Korea, Rep.', 'Country Name'] = 'South Korea'
table_melted_full.loc[table_melted_full['Country Name'] == 'Solomon Islands', 'Country Name'] = 'Solomon Is.'
table_melted_full.loc[table_melted_full['Country Name'] == 'S. Sudan', 'Country Name'] = 'S. Sudan'
#Missing Countries: S.Sudan and Côte d'Ivoire (present, but cannot add), Taiwan, Falkland Is., Antartica not in the table.


merged_data = world_map.merge(table_melted_full, left_on='name', right_on='Country Name', how='left')



fig = px.choropleth(merged_data, 
                    geojson=merged_data.geometry, 
                    locations=merged_data.index, 
                    color='% Change in Forest Area (1993-2021)',
                    hover_name='name',
                    hover_data=['% Change in Forest Area (1993-2021)'],
                    color_continuous_scale='Blackbody', #Inferno, Hot or Blackbody
                    projection='natural earth')

fig.update_geos(showcountries=True, countrycolor="lightgray", showcoastlines=True, coastlinecolor="white")

fig.update_layout(title='<b> Global Changes in Forest Area: From 1993 to 2021 <b>',
                  title_x=.5,
                  title_y=0.95,
                  font=dict(size=15),
                  )


fig.update_layout(
    coloraxis_colorbar=dict(title='<b>Forest Area Change<b>',
                            thickness=20,
                            len=0.6,
                            titlefont=dict(size=14),
                            tickfont=dict(size=12),
                            tickvals=[-20,-15, -10, -5, 0, 5, 10, 15],
                            ticktext=['-20%','-15%', '-10%', '-5%', '0%', '5%', '10%', '15%'], 
                            ))

fig.update_layout(margin={"r":0,"t":0,"l":30,"b":0}, width = 790, height = 450)
fig.update_geos(projection_scale=1.1)

hover_template = "<b>%{hovertext}</b><br>" + \
                 "%{customdata}% Forest Area Loss/Gain <br>" + \
                 "<extra></extra>"



fig.update_traces(hovertemplate=hover_template)
fig.show()
C:\Users\ERMCl\AppData\Local\Temp\ipykernel_20628\1488341276.py:2: FutureWarning:

The geopandas.dataset module is deprecated and will be removed in GeoPandas 1.0. You can get the original 'naturalearth_lowres' data from https://www.naturalearthdata.com/downloads/110m-cultural-vectors/.
  1. Are there countries that have increased in forest area during this time?
  2. Per year, is there a loss, neutrality, or increase in forest area globally?